//
//  jobs.h
//
//  Created by harrse on 5/5/17.
//  Copyright 2017 harrse. All rights reserved.
//

#ifndef __jobs_h
#define __jobs_h

#include <boost/thread.hpp>
#include <boost/bind.hpp>
#include <vector>
#include <deque>

namespace diylane {

	namespace jobs {

		struct Job {
			void* ctx;
			Job() {}
			virtual ~Job() {}
		};

		typedef void(*JobHandler)(Job*);

		struct Pool {
			boost::mutex mutex;
			std::vector<boost::thread*> workers;
			std::deque<Job*> jobs;
			JobHandler __handler;

			// configurations
			size_t max_workers = 100;
			bool shutdown = false;

			Pool() {

			}

			~Pool() {

			}

			void setHandler(JobHandler h) {
				__handler = h;
			}

			void runWorker() {
				while (!shutdown) {
					Job* job = pop();
					if (job) {
						if (__handler) {
							__handler(job);
						}
						delete job;
					}
                    boost::this_thread::sleep(boost::posix_time::milliseconds(100));
				}
			}

			Job* pop() {
				boost::lock_guard<boost::mutex> lock(mutex);
				if (jobs.empty()) {
					return NULL;
				}
				Job* job = jobs.front();
				jobs.pop_front();
				return job;
			}

			void add(Job* job) {
				boost::lock_guard<boost::mutex> lock(mutex);

				// Check if there are any pending jobs,
				// create one if there are pending jobs,
				// and current workers is not reach the limit.
				if ((!jobs.empty() && workers.size() < max_workers) || workers.size()<=0) {
					workers.push_back(new boost::thread(&Pool::runWorker, this));
				}

				// Add job to queue
				jobs.push_back(job);
			}

		};

	}

}

#endif
